using System;
using System.Collections.Generic;
using System.Text;
using FlatRedBall.AI.Pathfinding;
using FlatRedBall.Graphics.Model;

using FlatRedBall.Input;
using FlatRedBall.Utilities;

using FlatRedBall.Instructions;
using FlatRedBall.Math.Splines;
using BitmapFont = FlatRedBall.Graphics.BitmapFont;
using Cursor = FlatRedBall.Gui.Cursor;
using GuiManager = FlatRedBall.Gui.GuiManager;
// Generated Usings
using MultiplayerTD.Screens;
using Matrix = Microsoft.Xna.Framework.Matrix;
using FlatRedBall;
using FlatRedBall.Graphics;
using FlatRedBall.Math;
using MultiplayerTD.Performance;
using FlatRedBall.Broadcasting;
using MultiplayerTD.Entities;
using MultiplayerTD.Factories;
using FlatRedBall;
using FlatRedBall.Math.Geometry;
using FlatRedBall.ManagedSpriteGroups;
using FlatRedBall.Math.Geometry;
using FlatRedBall.Graphics.Animation;

#if XNA4
using Color = Microsoft.Xna.Framework.Color;
#else
using Color = Microsoft.Xna.Framework.Graphics.Color;
#endif

#if FRB_XNA || SILVERLIGHT
using Keys = Microsoft.Xna.Framework.Input.Keys;
using Vector3 = Microsoft.Xna.Framework.Vector3;
using Texture2D = Microsoft.Xna.Framework.Graphics.Texture2D;
#endif

#if FRB_XNA && !MONODROID
using Model = Microsoft.Xna.Framework.Graphics.Model;
#endif

namespace MultiplayerTD.Entities
{
	public partial class Tower : PositionedObject, IDestroyable, IPoolable
	{
        // This is made global so that static lazy-loaded content can access it.
        public static string ContentManagerName
        {
            get;
            set;
        }

		// Generated Fields
		#if DEBUG
		static bool HasBeenLoadedWithGlobalContentManager = false;
		#endif
		public enum VariableState
		{
			Uninitialized, //This exists so that the first set call actually does something
			Disable, 
			MayBuild, 
			Active, 
			Selected, 
			Hover
		}
		static object mLockObject = new object();
		static bool mHasRegisteredUnload = false;
		static bool IsStaticContentLoaded = false;
		private static AnimationChainList AnimationChainListFile;
		private static Scene SceneFile;
		
		private Circle mDetectionArea;
		public Circle DetectionArea
		{
			get
			{
				return mDetectionArea;
			}
		}
		static float DetectionAreaXReset;
		static float DetectionAreaYReset;
		static float DetectionAreaZReset;
		static float DetectionAreaXVelocityReset;
		static float DetectionAreaYVelocityReset;
		static float DetectionAreaZVelocityReset;
		static float DetectionAreaRotationXReset;
		static float DetectionAreaRotationYReset;
		static float DetectionAreaRotationZReset;
		static float DetectionAreaRotationXVelocityReset;
		static float DetectionAreaRotationYVelocityReset;
		static float DetectionAreaRotationZVelocityReset;
		private SpriteFrame mSpriteFrameInstance;
		public SpriteFrame SpriteFrameInstance
		{
			get
			{
				return mSpriteFrameInstance;
			}
		}
		static float SpriteFrameInstanceXReset;
		static float SpriteFrameInstanceYReset;
		static float SpriteFrameInstanceZReset;
		static float SpriteFrameInstanceXVelocityReset;
		static float SpriteFrameInstanceYVelocityReset;
		static float SpriteFrameInstanceZVelocityReset;
		static float SpriteFrameInstanceRotationXReset;
		static float SpriteFrameInstanceRotationYReset;
		static float SpriteFrameInstanceRotationZReset;
		static float SpriteFrameInstanceRotationXVelocityReset;
		static float SpriteFrameInstanceRotationYVelocityReset;
		static float SpriteFrameInstanceRotationZVelocityReset;
		static string SpriteFrameInstanceCurrentChainNameReset;
		static int SpriteFrameInstanceCurrentFrameIndexReset;
		static float SpriteFrameInstanceAlphaReset;
		static float SpriteFrameInstanceAlphaRateReset;
		private Circle mCollisionCircle;
		public Circle CollisionCircle
		{
			get
			{
				return mCollisionCircle;
			}
		}
		static float CollisionCircleXReset;
		static float CollisionCircleYReset;
		static float CollisionCircleZReset;
		static float CollisionCircleXVelocityReset;
		static float CollisionCircleYVelocityReset;
		static float CollisionCircleZVelocityReset;
		static float CollisionCircleRotationXReset;
		static float CollisionCircleRotationYReset;
		static float CollisionCircleRotationZReset;
		static float CollisionCircleRotationXVelocityReset;
		static float CollisionCircleRotationYVelocityReset;
		static float CollisionCircleRotationZVelocityReset;
		public float Damage = 0f;
		public float ShootingSpeed = 1f;
		public float SplashRadius = 0f;
		public float DetectionAreaRadius
		{
			get
			{
				return DetectionArea.Radius;
			}
			set
			{
				DetectionArea.Radius = value;
			}
		}
		public Color DetectionAreaColor
		{
			get
			{
				return DetectionArea.Color;
			}
			set
			{
				DetectionArea.Color = value;
			}
		}
		public bool DetectionAreaVisible
		{
			get
			{
				return DetectionArea.Visible;
			}
			set
			{
				DetectionArea.Visible = value;
			}
		}
		public string SpriteFrameInstanceCurrentChainName
		{
			get
			{
				return SpriteFrameInstance.CurrentChainName;
			}
			set
			{
				SpriteFrameInstance.CurrentChainName = value;
			}
		}
		public float CollisionCircleRadius
		{
			get
			{
				return CollisionCircle.Radius;
			}
			set
			{
				CollisionCircle.Radius = value;
			}
		}
		public bool CollisionCircleVisible
		{
			get
			{
				return CollisionCircle.Visible;
			}
			set
			{
				CollisionCircle.Visible = value;
			}
		}
		public int player = 0;
		public int Index { get; set; }
		public bool Used { get; set; }
		protected Layer LayerProvidedByContainer = null;

        public Tower(string contentManagerName) :
            this(contentManagerName, true)
        {
        }


        public Tower(string contentManagerName, bool addToManagers) :
			base()
		{
			// Don't delete this:
            ContentManagerName = contentManagerName;
            InitializeEntity(addToManagers);

		}

		protected virtual void InitializeEntity(bool addToManagers)
		{
			// Generated Initialize
			LoadStaticContent(ContentManagerName);
			mDetectionArea = new Circle();
			mSpriteFrameInstance = SceneFile.SpriteFrames.FindByName("AnimationChainListFile").Clone();
			mCollisionCircle = new Circle();
			
			PostInitialize();
			DetectionAreaXReset = DetectionArea.X;
			DetectionAreaYReset = DetectionArea.Y;
			DetectionAreaZReset = DetectionArea.Z;
			DetectionAreaXVelocityReset = DetectionArea.XVelocity;
			DetectionAreaYVelocityReset = DetectionArea.YVelocity;
			DetectionAreaZVelocityReset = DetectionArea.ZVelocity;
			DetectionAreaRotationXReset = DetectionArea.RotationX;
			DetectionAreaRotationYReset = DetectionArea.RotationY;
			DetectionAreaRotationZReset = DetectionArea.RotationZ;
			DetectionAreaRotationXVelocityReset = DetectionArea.RotationXVelocity;
			DetectionAreaRotationYVelocityReset = DetectionArea.RotationYVelocity;
			DetectionAreaRotationZVelocityReset = DetectionArea.RotationZVelocity;
			SpriteFrameInstanceXReset = SpriteFrameInstance.X;
			SpriteFrameInstanceYReset = SpriteFrameInstance.Y;
			SpriteFrameInstanceZReset = SpriteFrameInstance.Z;
			SpriteFrameInstanceXVelocityReset = SpriteFrameInstance.XVelocity;
			SpriteFrameInstanceYVelocityReset = SpriteFrameInstance.YVelocity;
			SpriteFrameInstanceZVelocityReset = SpriteFrameInstance.ZVelocity;
			SpriteFrameInstanceRotationXReset = SpriteFrameInstance.RotationX;
			SpriteFrameInstanceRotationYReset = SpriteFrameInstance.RotationY;
			SpriteFrameInstanceRotationZReset = SpriteFrameInstance.RotationZ;
			SpriteFrameInstanceRotationXVelocityReset = SpriteFrameInstance.RotationXVelocity;
			SpriteFrameInstanceRotationYVelocityReset = SpriteFrameInstance.RotationYVelocity;
			SpriteFrameInstanceRotationZVelocityReset = SpriteFrameInstance.RotationZVelocity;
			SpriteFrameInstanceCurrentChainNameReset = SpriteFrameInstance.CurrentChainName;
			SpriteFrameInstanceCurrentFrameIndexReset = SpriteFrameInstance.CurrentFrameIndex;
			SpriteFrameInstanceAlphaReset = SpriteFrameInstance.Alpha;
			SpriteFrameInstanceAlphaRateReset = SpriteFrameInstance.AlphaRate;
			CollisionCircleXReset = CollisionCircle.X;
			CollisionCircleYReset = CollisionCircle.Y;
			CollisionCircleZReset = CollisionCircle.Z;
			CollisionCircleXVelocityReset = CollisionCircle.XVelocity;
			CollisionCircleYVelocityReset = CollisionCircle.YVelocity;
			CollisionCircleZVelocityReset = CollisionCircle.ZVelocity;
			CollisionCircleRotationXReset = CollisionCircle.RotationX;
			CollisionCircleRotationYReset = CollisionCircle.RotationY;
			CollisionCircleRotationZReset = CollisionCircle.RotationZ;
			CollisionCircleRotationXVelocityReset = CollisionCircle.RotationXVelocity;
			CollisionCircleRotationYVelocityReset = CollisionCircle.RotationYVelocity;
			CollisionCircleRotationZVelocityReset = CollisionCircle.RotationZVelocity;
			if (addToManagers)
			{
				AddToManagers(null);
			}


		}

// Generated AddToManagers
		public virtual void AddToManagers (Layer layerToAddTo)
		{
			LayerProvidedByContainer = layerToAddTo;
			SpriteManager.AddPositionedObject(this);
			AddToManagersBottomUp(layerToAddTo);
			CustomInitialize();
		}

		public virtual void Activity()
		{
			// Generated Activity
			
			CustomActivity();
			
			// After Custom Activity
		}

		public virtual void Destroy()
		{
			// Generated Destroy
			SpriteManager.RemovePositionedObject(this);
			if (Used)
			{
				TowerFactory.MakeUnused(this, false);
			}
			if (DetectionArea != null)
			{
				ShapeManager.Remove(DetectionArea);
			}
			if (SpriteFrameInstance != null)
			{
				SpriteManager.RemoveSpriteFrame(SpriteFrameInstance);
			}
			if (CollisionCircle != null)
			{
				ShapeManager.Remove(CollisionCircle);
			}
			


			CustomDestroy();
		}

		// Generated Methods
public virtual void PostInitialize ()
{
	Damage = 0f;
	ShootingSpeed = 1f;
	SplashRadius = 0f;
	DetectionAreaRadius = 100f;
	DetectionAreaVisible = true;
	SpriteFrameInstanceCurrentChainName = "Default";
	CollisionCircleRadius = 14f;
	CollisionCircleVisible = false;
	player = 0;
}
public virtual void AddToManagersBottomUp (Layer layerToAddTo)
{
	// We move this back to the origin and unrotate it so that anything attached to it can just use its absolute position
	float oldRotationX = RotationX;
	float oldRotationY = RotationY;
	float oldRotationZ = RotationZ;
	
	float oldX = X;
	float oldY = Y;
	float oldZ = Z;
	
	X = 0;
	Y = 0;
	Z = 0;
	RotationX = 0;
	RotationY = 0;
	RotationZ = 0;
	ShapeManager.AddToLayer(mDetectionArea, layerToAddTo);
	DetectionArea.X = DetectionAreaXReset;
	DetectionArea.Y = DetectionAreaYReset;
	DetectionArea.Z = DetectionAreaZReset;
	DetectionArea.XVelocity = DetectionAreaXVelocityReset;
	DetectionArea.YVelocity = DetectionAreaYVelocityReset;
	DetectionArea.ZVelocity = DetectionAreaZVelocityReset;
	DetectionArea.RotationX = DetectionAreaRotationXReset;
	DetectionArea.RotationY = DetectionAreaRotationYReset;
	DetectionArea.RotationZ = DetectionAreaRotationZReset;
	DetectionArea.RotationXVelocity = DetectionAreaRotationXVelocityReset;
	DetectionArea.RotationYVelocity = DetectionAreaRotationYVelocityReset;
	DetectionArea.RotationZVelocity = DetectionAreaRotationZVelocityReset;
	if (mDetectionArea.Parent == null)
	{
		mDetectionArea.AttachTo(this, true);
	}
	SpriteManager.AddToLayer(mSpriteFrameInstance, layerToAddTo);
	SpriteFrameInstance.X = SpriteFrameInstanceXReset;
	SpriteFrameInstance.Y = SpriteFrameInstanceYReset;
	SpriteFrameInstance.Z = SpriteFrameInstanceZReset;
	SpriteFrameInstance.XVelocity = SpriteFrameInstanceXVelocityReset;
	SpriteFrameInstance.YVelocity = SpriteFrameInstanceYVelocityReset;
	SpriteFrameInstance.ZVelocity = SpriteFrameInstanceZVelocityReset;
	SpriteFrameInstance.RotationX = SpriteFrameInstanceRotationXReset;
	SpriteFrameInstance.RotationY = SpriteFrameInstanceRotationYReset;
	SpriteFrameInstance.RotationZ = SpriteFrameInstanceRotationZReset;
	SpriteFrameInstance.RotationXVelocity = SpriteFrameInstanceRotationXVelocityReset;
	SpriteFrameInstance.RotationYVelocity = SpriteFrameInstanceRotationYVelocityReset;
	SpriteFrameInstance.RotationZVelocity = SpriteFrameInstanceRotationZVelocityReset;
	SpriteFrameInstance.CurrentChainName = SpriteFrameInstanceCurrentChainNameReset;
	SpriteFrameInstance.CurrentFrameIndex = SpriteFrameInstanceCurrentFrameIndexReset;
	SpriteFrameInstance.Alpha = SpriteFrameInstanceAlphaReset;
	SpriteFrameInstance.AlphaRate = SpriteFrameInstanceAlphaRateReset;
	if (mSpriteFrameInstance.Parent == null)
	{
		mSpriteFrameInstance.AttachTo(this, true);
	}
	ShapeManager.AddToLayer(mCollisionCircle, layerToAddTo);
	CollisionCircle.X = CollisionCircleXReset;
	CollisionCircle.Y = CollisionCircleYReset;
	CollisionCircle.Z = CollisionCircleZReset;
	CollisionCircle.XVelocity = CollisionCircleXVelocityReset;
	CollisionCircle.YVelocity = CollisionCircleYVelocityReset;
	CollisionCircle.ZVelocity = CollisionCircleZVelocityReset;
	CollisionCircle.RotationX = CollisionCircleRotationXReset;
	CollisionCircle.RotationY = CollisionCircleRotationYReset;
	CollisionCircle.RotationZ = CollisionCircleRotationZReset;
	CollisionCircle.RotationXVelocity = CollisionCircleRotationXVelocityReset;
	CollisionCircle.RotationYVelocity = CollisionCircleRotationYVelocityReset;
	CollisionCircle.RotationZVelocity = CollisionCircleRotationZVelocityReset;
	if (mCollisionCircle.Parent == null)
	{
		mCollisionCircle.AttachTo(this, true);
	}
	X = oldX;
	Y = oldY;
	Z = oldZ;
	RotationX = oldRotationX;
	RotationY = oldRotationY;
	RotationZ = oldRotationZ;
}
public virtual void ConvertToManuallyUpdated ()
{
	this.ForceUpdateDependenciesDeep();
	SpriteManager.ConvertToManuallyUpdated(this);
}
public static void LoadStaticContent (string contentManagerName)
{
	ContentManagerName = contentManagerName;
	#if DEBUG
	if (contentManagerName == FlatRedBallServices.GlobalContentManager)
	{
		HasBeenLoadedWithGlobalContentManager = true;
	}
	else if (HasBeenLoadedWithGlobalContentManager)
	{
		throw new Exception("This type has been loaded with a Global content manager, then loaded with a non-global.  This can lead to a lot of bugs");
	}
	#endif
	if (IsStaticContentLoaded == false)
	{
		IsStaticContentLoaded = true;
		lock (mLockObject)
		{
			if (!mHasRegisteredUnload && ContentManagerName != FlatRedBallServices.GlobalContentManager)
			{
				FlatRedBallServices.GetContentManagerByName(ContentManagerName).AddUnloadMethod("TowerStaticUnload", UnloadStaticContent);
				mHasRegisteredUnload = true;
			}
		}
		bool registerUnload = false;
		if (!FlatRedBallServices.IsLoaded<AnimationChainList>(@"content/entities/tower/animationchainlistfile.achx", ContentManagerName))
		{
			registerUnload = true;
		}
		AnimationChainListFile = FlatRedBallServices.Load<AnimationChainList>(@"content/entities/tower/animationchainlistfile.achx", ContentManagerName);
		if (!FlatRedBallServices.IsLoaded<Scene>(@"content/entities/tower/scenefile.scnx", ContentManagerName))
		{
			registerUnload = true;
		}
		SceneFile = FlatRedBallServices.Load<Scene>(@"content/entities/tower/scenefile.scnx", ContentManagerName);
		if (registerUnload && ContentManagerName != FlatRedBallServices.GlobalContentManager)
		{
			lock (mLockObject)
			{
				if (!mHasRegisteredUnload && ContentManagerName != FlatRedBallServices.GlobalContentManager)
				{
					FlatRedBallServices.GetContentManagerByName(ContentManagerName).AddUnloadMethod("TowerStaticUnload", UnloadStaticContent);
					mHasRegisteredUnload = true;
				}
			}
		}
		CustomLoadStaticContent(contentManagerName);
	}
}
public static void UnloadStaticContent ()
{
	IsStaticContentLoaded = false;
	mHasRegisteredUnload = false;
	if (AnimationChainListFile != null)
	{
		AnimationChainListFile= null;
	}
	if (SceneFile != null)
	{
		SceneFile.RemoveFromManagers(ContentManagerName != "Global");
		SceneFile= null;
	}
}
public static object GetStaticMember (string memberName)
{
	switch(memberName)
	{
		case  "AnimationChainListFile":
			return AnimationChainListFile;
		case  "SceneFile":
			return SceneFile;
	}
	return null;
}
static VariableState mLoadingState = VariableState.Uninitialized;
public static VariableState LoadingState
{
	get
	{
		return mLoadingState;
	}
	set
	{
		mLoadingState = value;
	}
}
VariableState mCurrentState = VariableState.Uninitialized;
public VariableState CurrentState
{
	get
	{
		return mCurrentState;
	}
	set
	{
		mCurrentState = value;
		switch(mCurrentState)
		{
			case  VariableState.Disable:
				DetectionAreaVisible = false;
				SpriteFrameInstanceCurrentChainName = "Default";
				CollisionCircleVisible = false;
				break;
			case  VariableState.MayBuild:
				DetectionAreaVisible = true;
				SpriteFrameInstanceCurrentChainName = "Default";
				CollisionCircleVisible = false;
				break;
			case  VariableState.Active:
				DetectionAreaVisible = false;
				SpriteFrameInstanceCurrentChainName = "Default";
				CollisionCircleVisible = false;
				break;
			case  VariableState.Selected:
				DetectionAreaVisible = true;
				SpriteFrameInstanceCurrentChainName = "Default";
				CollisionCircleVisible = false;
				break;
			case  VariableState.Hover:
				DetectionAreaVisible = false;
				SpriteFrameInstanceCurrentChainName = "Default";
				CollisionCircleVisible = false;
				break;
		}
	}
}
public MethodInstruction<Tower> InterpolateToState (VariableState stateToInterpolateTo, double secondsToTake)
{
	switch(stateToInterpolateTo)
	{
		case  VariableState.Disable:
			break;
		case  VariableState.MayBuild:
			break;
		case  VariableState.Active:
			break;
		case  VariableState.Selected:
			break;
		case  VariableState.Hover:
			break;
	}
	var instruction = new MethodInstruction<Tower>(this, "StopStateInterpolation", new object[]{stateToInterpolateTo}, TimeManager.CurrentTime + secondsToTake);
	this.Instructions.Add(instruction);
	return instruction;
}
public void StopStateInterpolation (VariableState stateToStop)
{
	switch(stateToStop)
	{
		case  VariableState.Disable:
			break;
		case  VariableState.MayBuild:
			break;
		case  VariableState.Active:
			break;
		case  VariableState.Selected:
			break;
		case  VariableState.Hover:
			break;
	}
	CurrentState = stateToStop;
}
public void InterpolateBetween (VariableState firstState, VariableState secondState, float interpolationValue)
{
	bool setDamage = true;
	Single DamageFirstValue = 0;
	Single DamageSecondValue = 0;
	bool setShootingSpeed = true;
	Single ShootingSpeedFirstValue = 0;
	Single ShootingSpeedSecondValue = 0;
	bool setSplashRadius = true;
	Single SplashRadiusFirstValue = 0;
	Single SplashRadiusSecondValue = 0;
	bool setDetectionAreaRadius = true;
	Single DetectionAreaRadiusFirstValue = 0;
	Single DetectionAreaRadiusSecondValue = 0;
	switch(firstState)
	{
		case  VariableState.Disable:
			setDamage = false;
			setShootingSpeed = false;
			setSplashRadius = false;
			setDetectionAreaRadius = false;
			break;
		case  VariableState.MayBuild:
			break;
		case  VariableState.Active:
			break;
		case  VariableState.Selected:
			break;
		case  VariableState.Hover:
			break;
	}
	switch(secondState)
	{
		case  VariableState.Disable:
			setDamage = false;
			setShootingSpeed = false;
			setSplashRadius = false;
			setDetectionAreaRadius = false;
			break;
		case  VariableState.MayBuild:
			break;
		case  VariableState.Active:
			break;
		case  VariableState.Selected:
			break;
		case  VariableState.Hover:
			break;
	}
	if (setDamage)
	{
		Damage = DamageFirstValue * (1 - interpolationValue) + DamageSecondValue * interpolationValue;
	}
	if (setShootingSpeed)
	{
		ShootingSpeed = ShootingSpeedFirstValue * (1 - interpolationValue) + ShootingSpeedSecondValue * interpolationValue;
	}
	if (setSplashRadius)
	{
		SplashRadius = SplashRadiusFirstValue * (1 - interpolationValue) + SplashRadiusSecondValue * interpolationValue;
	}
	if (setDetectionAreaRadius)
	{
		DetectionAreaRadius = DetectionAreaRadiusFirstValue * (1 - interpolationValue) + DetectionAreaRadiusSecondValue * interpolationValue;
	}
}
object GetMember (string memberName)
{
	switch(memberName)
	{
	}
	return null;
}

    }
	
	
	// Extra classes
	public static class TowerExtensionMethods
	{
	}
	
}
